package cn.shop.front.service.impl;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.SaSessionCustomUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.shop.base.MyServiceImpl;
import cn.shop.front.service.BankCardService;
import cn.shop.front.service.FrontUserService;
import cn.shop.front.util.CurrentUserUtil;
import cn.shop.thiredparty.entity.AuthResult;
import cn.shop.thiredparty.entity.BankAuthCode;
import cn.shop.thiredparty.entity.IdAuthCode;
import cn.shop.thiredparty.service.ThiredpartyService;
import cn.shop.transcation.bankcard.entity.BankAndIDInfo;
import cn.shop.transcation.bankcard.entity.BankCard;
import cn.shop.transcation.bankcard.mapper.BankCardMapper;
import cn.shop.transcation.frontUserModule.FrontUser;
import cn.shop.utils.ApiResult;
import cn.shop.utils.Putif;
import cn.shop.utils.constant.Constant;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.shop.utils.ApiResult.fail;

/**
 * @author : 李一涵
 * @date : Created in 2022-2-16 14:57
 * @description :
 */
@Slf4j
@Service
public class BankCardServiceImpl extends MyServiceImpl<BankCardMapper, BankCard> implements BankCardService {
    @Resource
    private ThiredpartyService thiredpartyService;
    @Resource
    private BankCardMapper bankCardMapper;
    @Resource
    private FrontUserService frontUserService;

    @Override
    public Map<String, Object> getInfo(long id, long ownerId) {
        BankCard card = getOne(Wrappers.<BankCard>lambdaQuery()
                .eq(BankCard::getId, id)
                .eq(BankCard::getOwnerId, ownerId));
        return format(card);
    }

    @Override
    public boolean updateInfo(long ownerId, BankCard update) {
        return update(update, Wrappers.<BankCard>lambdaQuery()
                .eq(BankCard::getOwnerId, ownerId)
                .eq(BankCard::getId, update.getId()));
    }

    @Override
    public long getBankCount(long ownerId) {
        return count(Wrappers.<BankCard>lambdaQuery()
                .eq(BankCard::getOwnerId, ownerId));
    }

    @Override
    public List<Map<String, Object>> bankList(long ownerId) {
        List<BankCard> cards = list(Wrappers.<BankCard>lambdaQuery()
                .eq(BankCard::getOwnerId, ownerId));
        return cards.stream().map(this::format).collect(Collectors.toList());
    }

    private Map<String, Object> format(BankCard card) {
        return Putif.start()
                .anyway("id", card.getId())
                .anyway("bankName", card.getBankName())
                .anyway("cardDefault", card.getCardDefault())
                .anyway("cardNo", DesensitizedUtil.bankCard(card.getCardNo()))
                .anyway("name", DesensitizedUtil.chineseName(card.getName()))
                .anyway("mobile", DesensitizedUtil.mobilePhone(card.getMobile()))
                .get();
    }

    /**
     * 获取登录用户的银行卡信息实名信息和账号信息
     *
     * @param userId
     * @return cn.shop.transcation.bankcard.entity.BankAndIDInfo
     * @author 王鹤然
     * @date 2023/1/30 0030 上午 10:26
     */
    @Override
    public BankAndIDInfo getBankAndIDInfo(Long userId) {
        BankAndIDInfo bankAndIDInfo = bankCardMapper.getBankAndIDInfo(userId);
        if (bankAndIDInfo!=null){
            bankAndIDInfo.setName(DesensitizedUtil.chineseName(bankAndIDInfo.getName()));
            bankAndIDInfo.setIdCard(DesensitizedUtil.idCardNum(bankAndIDInfo.getIdCard(),2, 2));
        }
        return bankAndIDInfo;
    }

    /**
     * 提交登录用户的银行卡信息实名信息和账号信息
     *
     * @param bankAndIDInfo
     * @return boolean
     * @author 王鹤然
     * @date 2023/1/30 0030 上午 10:48
     */
    @Override
    @Transactional
    public ApiResult<Map<String, Object>> submitBankAndID(BankAndIDInfo bankAndIDInfo) {
        //实名认证
        String name = StrUtil.trim(bankAndIDInfo.getName());
        String identityCard = StrUtil.trim(bankAndIDInfo.getIdCard());
        AuthResult result = thiredpartyService.idCardAuth(identityCard, name);
        log.info("实名认证结果: {}", result);
        if (!IdAuthCode.C10000.code().equals(result.getCode())) {
            return ApiResult.fail("实名认证失败");
        }
        if (!AuthResult.State.SAME.code().equals(result.getData().getResult())) {
            return ApiResult.fail("请检查身份证与姓名是否一致");
        }
        int age = IdcardUtil.getAgeByIdCard(identityCard);
        if (age < 18) {
            return ApiResult.fail("未成年人无法通过实名认证！");
        }
        // 修改用户信息
        FrontUser user = new FrontUser();
        user.setId(CurrentUserUtil.getUserId());
        user.setName(bankAndIDInfo.getName());
        user.setIdentityCard(bankAndIDInfo.getIdCard());
        user.setCertification(true);
        //手机号短信验证码校验
        if (StrUtil.isNotBlank(bankAndIDInfo.getCode())){
            //只允许修改自己的信息
            String key = Constant.SMS_CODE + CurrentUserUtil.getUserId();
            SaSession session = SaSessionCustomUtil.getSessionById(key);
            Assert.notNull(session, "验证码已失效");
            String c = session.getString("code");
            log.info("获取缓存验证码：key={}，code={}，session={}, 前端code={}", key, c, session, bankAndIDInfo.getCode());
            if (StrUtil.isBlank(c) || !c.equals(bankAndIDInfo.getCode())) {
                return fail("验证码不正确");
            }
            session.clear();
            user.setPhone(bankAndIDInfo.getPhone());
        }
        // 密码加密
        user.setTransactionPassword(DigestUtil.bcrypt(bankAndIDInfo.getTransactionPassword()));
        frontUserService.updateById(user);
        //银行验证
        AuthResult bankResult = thiredpartyService.bankAuth(bankAndIDInfo.getCardNo(), bankAndIDInfo.getIdCard(), bankAndIDInfo.getMobile(), bankAndIDInfo.getName());
        log.info("银行卡验证结果: {}", bankResult);
        if (bankResult == null) {
            log.error("银行卡认证接口失败，接口返回无结果");
            return ApiResult.fail("银行卡认证失败");
        }
        if (!BankAuthCode.C10000.code().equals(bankResult.getCode())) {
            return ApiResult.fail("银行卡认证失败");
        }
        if (!AuthResult.State.SAME.code().equals(bankResult.getData().getState())) {
            return ApiResult.fail("请检查银行卡信息是否正确");
        }
        // 添加银行卡信息
        BankCard bankCard = new BankCard();
        bankCard.setCardNo(bankAndIDInfo.getCardNo());
        bankCard.setBankName(bankAndIDInfo.getBankName());
        bankCard.setName(bankAndIDInfo.getName());
        bankCard.setOwnerId(CurrentUserUtil.getUserId());
        bankCard.setMobile(bankAndIDInfo.getMobile());
        bankCard.setCardDefault(true);
        return ApiResult.result(save(bankCard));
    }

    /**
     * 修改默认银行卡
     *
     * @param bankCard
     * @return
     */
    @Override
    @Transactional
    public boolean changeDefault(BankCard bankCard) {
        // 获取到上一个默认的银行卡数据 修改默认字段为false
         bankCardMapper.changeOriginalDefault(CurrentUserUtil.getUserId());
         bankCard.setCardDefault(true);
        return updateById(bankCard);
    }
}
